/*
 * Universidade Estadual de Campinas - UNICAMP
 * MC823 - Laboratório de Redes
 * Alunos:
 *         Daniel Camillo C. Farias  RA: 059878
 *         Vitor Hugo Mickus Rodrigues RA: 072627
 * Professor:
 *         Paulo Lício e Celio
 *
 * Client program for Network Labs. Simulate an ECHO program.
 *
 */

#include "client_echo.h"

int sockfd;
int numberOfTries = 0;
char send_buf[MAXDATASIZE];
struct sockaddr_in their_addr; /* connector's address information */

void  ALARMhandler(int sig) {
  _SEND_TO_SERVER(sockfd, send_buf, strlen(send_buf),(struct sockaddr *)&their_addr, sizeof(struct sockaddr));

  numberOfTries++;
  if (numberOfTries >= MAX_NUMBER_OF_TRIES) {
    printf("Número de tentativas de envio excedida.\n");
    exit(1);
  }

  alarm(ALARM_TIMEOUT);
}

/*
 * Main Function, start of the program.
 *      Input:
 *            int argc:  number of parameters passed in command line.
 *            char* argv[]: the parameters passed in command line.
 *      Output:
 *            int : status of the program.             
 */
int main(int argc, char* argv[]) {
  //Local Variables
  int numbytes;
  int counter_send = 0, counter_received = 0;
  int max_line_size = 0;
  int total_chars_sent = 0;
  int count_chars_sent = 0, count_chars_received = 0;
  char receive_buf[MAXDATASIZE];
  struct hostent *he;
  clock_t initialTime;
  socklen_t addrlen;

  //Inicia contagem de tempo
  initialTime = times(NULL);
 
  //Get the host info 
  if ( (he=gethostbyname(argv[1]) ) == NULL) {  
    perror("gethostbyname");
    exit(1);
  }
  
  
  //create socket de012scriptor
  //   AF_INET -> used domain ( internet )
  //   SOCK_STREAM -> socket type ( pipe type )
  //   0 -> protocol ( should always be 0 )
  if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
    perror("socket");
    exit(1);
  }  
    
  their_addr.sin_family = AF_INET;         /* host byte order */
  their_addr.sin_port = htons(PORT);       /* short, network byte order */
  their_addr.sin_addr = *((struct in_addr *)he->h_addr);
  bzero(&(their_addr.sin_zero), 8);        /* zero the rest of the struct */
    
  // UDP is not connection based, but connect can be used to open a file 
  // descriptor and use send/recv or write/read operations on the fd
  _CONNECT(sockfd, (struct sockaddr *) &their_addr , sizeof(struct sockaddr_in))

  signal(SIGALRM, ALARMhandler); 

  // Envia byte 0
  _SEND_TO_SERVER(sockfd, NULL , 0, (struct sockaddr *)&their_addr, sizeof(struct sockaddr_in));
  _RECV_FROM_SERVER(sockfd, NULL , 0, (struct sockaddr *)&their_addr, sizeof(struct sockaddr_in));

  //Read data from keyboard
  while ( fgets( send_buf, MAXDATASIZE, stdin ) != NULL ) {    

    numberOfTries = 0;
    
    // Send data to server
    count_chars_sent = _SEND_TO_SERVER(sockfd, send_buf, strlen(send_buf),(struct sockaddr *)&their_addr, sizeof(struct sockaddr));

    total_chars_sent += count_chars_sent;

    //    alarm(ALARM_TIMEOUT);
      
    // Update Controls
    counter_send++;
    if(count_chars_sent-1 > max_line_size ) {
      max_line_size = count_chars_sent-1;
    }

    // Receive data from server
    /*    if ( (numbytes = _RECV_FROM_SERVER(sockfd, receive_buf, MAXDATASIZE, (struct sockaddr *)&their_addr, &addrlen)) == -1) {
      perror("recv");
      exit(1);
      }

    receive_buf[numbytes] = '\0';

    count_chars_received += strlen(receive_buf);    
    counter_received++;   

    printf("%s",receive_buf);*/
  }

  //Envia byte 0
    _SEND_TO_SERVER(sockfd, NULL , 0, (struct sockaddr *)&their_addr, sizeof(struct sockaddr));
  
  // Print some information
  fprintf(stderr, "\n----Information----\n");
  fprintf(stderr,"Sent lines: %d\n", counter_send);
  fprintf(stderr,"Biggest line: %d\n", max_line_size);
  fprintf(stderr,"Total chars sent: %d\n", total_chars_sent);
  fprintf(stderr,"Received lines: %d\n", counter_received);
  fprintf(stderr,"Total chars received: %d\n", count_chars_received);
  fprintf(stderr,"time: %.1f seconds\n", (double)(times(NULL) - initialTime)/(double)sysconf(_SC_CLK_TCK));
  fprintf(stderr,"\n--------END--------\n");

  close(sockfd);
  
  return 0;
  
}
